/*
 * Copyright 2017 Matthew Tamlin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.matthewtamlin.fortytwo.library_tests;

import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.ComponentState;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.window.service.WindowManager;

import com.matthewtamlin.fortytwo.library.answer_group.AnswerGroup;
import com.matthewtamlin.fortytwo.library.answer_view.AnswerView;

import java.util.ArrayList;
import java.util.List;

/**
 * An abstract test harness for displaying and interacting with an implementation of the {@link
 * AnswerGroup} interface.
 */
public abstract class AnswerGroupTestHarness extends ControlsOverViewTestHarness<AnswerGroup> {
    /**
     * getAnswerView
     *
     * @return a new AnswerView which can be displayed in the test answer group, not null
     */
    public abstract AnswerView getAnswerView();

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        WindowManager.getInstance().getTopWindow().get().setStatusBarColor(Color.getIntColor("#666666"));

        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.BLACK.getValue()));
        getRootView().setBackground(shapeElement);

        getControlsContainer().addComponent(createAddAnswersButton());
        getControlsContainer().addComponent(createAddAnswerButton());
        getControlsContainer().addComponent(createRemoveAnswerButton());
        getControlsContainer().addComponent(createClearAnswersButton());
        getControlsContainer().addComponent(createAllowSelectionChangesWhenMarkedButton());
        getControlsContainer().addComponent(createDisallowSelectionChangesWhenMarkedButton());
        getControlsContainer().addComponent(createMarkAllButton());
        getControlsContainer().addComponent(createUnmarkAllButton());
    }

    /**
     * Creates a button which adds multiple answer views to the test view when clicked.
     *
     * @return the button
     */
    private Button createAddAnswersButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Add multiple answers");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                final List<AnswerView> answers = new ArrayList<>();

                answers.add(getAnswerView());
                answers.add(getAnswerView());
                answers.add(getAnswerView());

                getTestView().addAnswers(answers);
            }
        });

        return b;
    }

    /**
     * Creates a button which adds a single answer view to the test view when clicked.
     *
     * @return the button
     */
    private Button createAddAnswerButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Add one answer");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                getTestView().addAnswer(getAnswerView());
            }
        });

        return b;
    }

    /**
     * Creates a button which removes the first answer view from the test view when clicked.
     *
     * @return the button
     */
    private Button createRemoveAnswerButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Remove first answer");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (!getTestView().getAnswers().isEmpty()) {
                    final AnswerView firstAnswer = getTestView().getAnswers().get(0);
                    getTestView().removeAnswer(firstAnswer);
                }
            }
        });

        return b;
    }

    /**
     * Creates a button which clears all answer views from the test view when clicked.
     *
     * @return the button
     */
    private Button createClearAnswersButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Clear answers");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                getTestView().clearAnswers();
            }
        });

        return b;
    }

    /**
     * Creates a button which when clicked, allows marked views to be selected and unselected.
     *
     * @return the button
     */
    private Button createAllowSelectionChangesWhenMarkedButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Unlock when marked");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                getTestView().allowSelectionChangesWhenMarked(true);
            }
        });

        return b;
    }

    /**
     * Creates a button which when clicked, prevents marked views from being selected and
     * unselected.
     *
     * @return the button
     */
    private Button createDisallowSelectionChangesWhenMarkedButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Lock when marked");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                getTestView().allowSelectionChangesWhenMarked(false);
            }
        });

        return b;
    }

    /**
     * Creates a button which when clicked, marks all answer views in the test view.
     *
     * @return the button
     */
    private Button createMarkAllButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Mark all");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                for (final AnswerView answerView : getTestView().getAnswers()) {
                    answerView.setMarkedStatus(true, true);
                }
            }
        });

        return b;
    }

    /**
     * Creates a button which when clicked, unmarks all answer views in the test view.
     *
     * @return the button
     */
    private Button createUnmarkAllButton() {
        final Button b = new Button(this);
        configBtn(b);
        b.setText("Unmark all");

        b.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                for (final AnswerView answerView : getTestView().getAnswers()) {
                    answerView.setMarkedStatus(false, true);
                }
            }
        });

        return b;
    }

    private void configBtn(Button b) {
        int padding = 20;
        int paddingTop = 25;
        b.setPadding(padding, paddingTop, padding, paddingTop);
        b.setTextSize(40);
        b.setTextColor(new Color(Color.getIntColor("#333333")));

        StateElement stateElement = new StateElement();
        ShapeElement selectedElement = new ShapeElement(getContext(), ResourceTable.Graphic_btn_bg_press);
        ShapeElement emptyElement = new ShapeElement(getContext(), ResourceTable.Graphic_btn_bg_normal);
        stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_PRESSED}, selectedElement);
        stateElement.addState(new int[]{ComponentState.COMPONENT_STATE_EMPTY}, emptyElement);
        b.setBackground(stateElement);

        b.setLayoutConfig(new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,
            ComponentContainer.LayoutConfig.MATCH_CONTENT));

        int margin = 10;
        b.setMarginRight(margin);
        b.setMarginBottom(margin);
        b.setMarginLeft(margin);
        b.setMarginTop(margin);

        b.setFont(Font.DEFAULT_BOLD);
    }
}